package top.yjp.jtf.plugin;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.EditorSettings;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorLocation;
import com.intellij.openapi.fileEditor.FileEditorState;
import com.intellij.openapi.fileEditor.FileEditorStateLevel;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.EditorTextField;
import com.intellij.ui.components.JBPanel;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.ui.components.JBTabbedPane;
import com.intellij.ui.table.JBTable;
import com.intellij.json.JsonFileType;
import top.yjp.jtf.plugin.ExcelFileType;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.table.DefaultTableModel;

public class ExcelFileEditor implements FileEditor, DumbAware, Disposable {
    private final VirtualFile file;
    private final JBPanel rootPanel;
    private final JBTabbedPane tabbedPane;
    private FileEditorState state;
    private EditorTextField editorTextField;
    private int currentRow = -1; // 当前编辑的行
    private int currentColumn = -1; // 当前编辑的列

    private final Map<String,List<String>> hiddenColumnsMap = new HashMap<>();
    private Project project;
    public ExcelFileEditor(@NotNull Project project, @NotNull VirtualFile virtualFile) {
        this.project = project;
        this.rootPanel = new JBPanel(new BorderLayout());
        this.file = virtualFile;
        this.tabbedPane = new JBTabbedPane();

        // 创建编辑面板
        JPanel editorPanel = new JPanel(new BorderLayout());
        
        // 创建EditorTextField，支持语法高亮和自动完成
        this.editorTextField = new EditorTextField("", project, FileTypes.PLAIN_TEXT) {
            @NotNull
            @Override
            protected EditorEx createEditor() {
                EditorEx editor = super.createEditor();
                EditorSettings settings = editor.getSettings();
                settings.setLineNumbersShown(true);
                settings.setAutoCodeFoldingEnabled(true);
                settings.setFoldingOutlineShown(true);
                settings.setRightMarginShown(true);
                settings.setAdditionalLinesCount(2);
                settings.setAdditionalColumnsCount(3);
                settings.setLineCursorWidth(2);
                return editor;
            }
        };
        
        // 设置固定高度
        Dimension preferredSize = new Dimension(300, 20 * 5); // 宽度 300，高度 100
        editorTextField.setPreferredSize(preferredSize);
        editorPanel.add(editorTextField, BorderLayout.CENTER);

        JButton saveButton = new JButton("保存");
        saveButton.addActionListener(e -> saveCurrentCell());
        editorPanel.add(saveButton, BorderLayout.EAST);

        this.rootPanel.add(editorPanel, BorderLayout.NORTH);
        this.rootPanel.add(tabbedPane, BorderLayout.CENTER);

        String filePath = virtualFile.getPath();
        String[] sheetNames = new String[]{"TestData", "DbData", "MockData", "DefaultObjectData"};

        // 读取 Excel 数据
        for (String sheetName : sheetNames) {
            List<Map<Integer, String>> data = EasyExcel.read(new File(filePath))
                    .excelType(ExcelTypeEnum.XLSX)
                    .sheet(sheetName)
                    .headRowNumber(1)
                    .doReadSync();
            hiddenColumnsMap.put(sheetName,new ArrayList<>());
            int columnCount = data.get(0).size();
            String[] columnNames = new String[columnCount];
            for (int i = 0; i < columnCount; i++) {
                columnNames[i] = data.get(0).get(i); // 使用实际列名
            }

            DefaultTableModel model = new DefaultTableModel(columnNames, 0);
            if (data.size() > 1) {
                for (int i = 1; i < data.size(); i++) {
                    Map<Integer, String> row = data.get(i);
                    Object[] rowData = new Object[columnNames.length];
                    for (Map.Entry<Integer, String> entry : row.entrySet()) {
                        rowData[entry.getKey()] = entry.getValue();
                    }
                    model.addRow(rowData);
                }
            }

            JBTable table = new JBTable(model);
            table.setFillsViewportHeight(true);
            table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); // 禁用自动调整列宽
            // 设置列宽
            for (int i = 0; i < columnCount; i++) {
                TableColumn column = table.getColumnModel().getColumn(i);
                String columnName = columnNames[i];

                // 创建一个标签来计算列标题的宽度
                JLabel label = new JLabel(columnName);
                label.setFont(table.getTableHeader().getFont()); // 设置与表头相同的字体
                int width = label.getPreferredSize().width + table.getIntercellSpacing().width; // 加上间距

                // 确保宽度大于最小宽度和首选宽度
                column.setMinWidth(30); // 最小宽度
                column.setPreferredWidth(Math.max(width, 100)); // 设置为标题的宽度或默认宽度
            }
            table.setRowHeight(30); // 设置默认行高
            // 自定义表头事件
            JTableHeader header = table.getTableHeader();
            header.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
//                    int column = header.columnAtPoint(e.getPoint());
                    if (SwingUtilities.isRightMouseButton(e)) {
                        showColumnSelector(table, e,sheetName);
                    }
                }
            });
            // 监听数据行单击事件
            table.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    if (e.getClickCount() == 1) {
                        int row = table.rowAtPoint(e.getPoint());
                        int column = table.columnAtPoint(e.getPoint());
                        if (row >= 0 && column >= 0) {
                            editCell(table, row, column);
                        }
                    }
                }
            });

            // 创建滚动面板
            JBScrollPane scrollPane = new JBScrollPane(table);
            scrollPane.setHorizontalScrollBarPolicy(JBScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
            scrollPane.setVerticalScrollBarPolicy(JBScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);

            // 将每个 sheet 添加到标签页中
            tabbedPane.addTab(sheetName, scrollPane);
            tabbedPane.addChangeListener(new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                    currentColumn = -1;
                    currentRow=-1;
                    editorTextField.setText("");
                }
            });
        }
    }

    private void showColumnSelector(JBTable table, MouseEvent mouseEvent,String sheetName) {
        JPopupMenu popupMenu = new JPopupMenu();
        JTableHeader header = table.getTableHeader();
        // 添加选择项
        for (int i = 0; i < table.getColumnCount(); i++) {
            final int colIndex = i;
            String columnName = table.getColumnName(i);
            List<String> hiddenColumns = hiddenColumnsMap.getOrDefault(sheetName,new ArrayList<>());
            boolean checked = !hiddenColumns.contains(columnName);
            JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem(columnName, checked);
            menuItem.addActionListener(e -> {
                TableColumn column = table.getColumnModel().getColumn(colIndex);
                boolean selected = menuItem.isSelected();
                menuItem.setState(checked);
                if(checked) {
                    hiddenColumnsMap.get(sheetName).add(columnName);
                }else{
                    hiddenColumnsMap.get(sheetName).remove(columnName);
                }
                column.setMinWidth(selected ? 30 : 0);
                //column.setMaxWidth(selected ? Integer.MAX_VALUE : 0);
                column.setPreferredWidth(selected ? 100 : 0);
                table.setFillsViewportHeight(true);
                table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
                table.revalidate();
                table.repaint();
            });
            popupMenu.add(menuItem);
        }

        // 获取点击位置的坐标
        int x = mouseEvent.getX(); // 使用点击位置的横坐标
        int y = header.getY() + header.getHeight(); // 表头底部的纵坐标

        // 确保弹出菜单水平对齐到列的左侧
        TableColumnModel columnModel = header.getColumnModel();
        int columnIndex = header.getTable().columnAtPoint(mouseEvent.getPoint());
        if (columnIndex >= 0) {
            int columnWidth = columnModel.getColumn(columnIndex).getWidth();
            Rectangle headerRect = header.getHeaderRect(columnIndex); // 获取列头的矩形区域
            x = headerRect.x; // 列的起始横坐标
        }

        // 显示弹出菜单
        popupMenu.show(header, x, y);
    }

    private void editCell(JBTable table, int row, int column) {
        currentRow = row;
        currentColumn = column;
        currentTable = table; // 设置当前表格
        Object currentValue = table.getValueAt(row, column);
        String columnName = table.getColumnName(column);
        String content = currentValue != null ? currentValue.toString() : "";
        
        // 根据列名或内容设置适当的文件类型
        FileType fileType = determineFileType(columnName, content);
        
        // 创建新的EditorTextField以应用新的文件类型
        JPanel editorPanel = (JPanel) rootPanel.getComponent(0);
        editorPanel.remove(editorTextField);
        
        EditorTextField newEditorField = new EditorTextField(content, project, fileType) {
            @Override
            protected EditorEx createEditor() {
                EditorEx editor = super.createEditor();
                EditorSettings settings = editor.getSettings();
                settings.setLineNumbersShown(true);
                settings.setAutoCodeFoldingEnabled(true);
                settings.setFoldingOutlineShown(true);
                settings.setRightMarginShown(true);
                settings.setAdditionalLinesCount(2);
                settings.setAdditionalColumnsCount(3);
                settings.setLineCursorWidth(2);
                return editor;
            }
        };
        
        // 添加键盘监听器，处理Enter和Escape键
        newEditorField.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_ENTER && e.isControlDown()) {
                    // Ctrl+Enter保存并关闭
                    saveCurrentCell();
                    e.consume();
                } else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
                    // Escape取消编辑
                // 取消编辑，恢复原始值
                cancelEditing();
                e.consume();
                }
            }
        });
        
        // 设置快捷键
        InputMap inputMap = newEditorField.getInputMap(JComponent.WHEN_FOCUSED);
        ActionMap actionMap = newEditorField.getActionMap();
        
        // 保存动作
        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, KeyEvent.CTRL_DOWN_MASK), "saveCell");
        actionMap.put("saveCell", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                saveCurrentCell();
            }
        });
        
        // 取消动作
        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "cancelEdit");
        actionMap.put("cancelEdit", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // 取消编辑
                cancelEditing();
            }
        });
        
        // 设置固定高度
        Dimension preferredSize = new Dimension(300, 20 * 5);
        newEditorField.setPreferredSize(preferredSize);
        
        // 替换旧的编辑器
        if (editorTextField != null && editorTextField.getEditor() != null) {
            EditorFactory.getInstance().releaseEditor(editorTextField.getEditor());
        }
        
        editorTextField = newEditorField;
        editorPanel.add(editorTextField, BorderLayout.CENTER);
        editorPanel.revalidate();
        editorPanel.repaint();
        
        editorTextField.requestFocus(); // 聚焦到文本区域
    }
    
    /**
     * 根据列名和内容确定适合的文件类型
     */
    private FileType determineFileType(String columnName, String content) {
        // 根据列名判断
        if (columnName != null) {
            columnName = columnName.toLowerCase();
            
            // JSON相关列
            if (columnName.contains("json") || columnName.contains("config") || columnName.contains("param")) {
                return JsonFileType.INSTANCE;
            }
            
            // 断言相关列
            if (columnName.contains("assert") || columnName.contains("condition") || 
                columnName.contains("expect") || columnName.contains("validate")) {
                return ExcelFileType.INSTANCE;
            }
            
            // Java代码相关列
            if (columnName.contains("code") || columnName.contains("java") || 
                columnName.contains("class") || columnName.contains("method")) {
                return FileTypes.PLAIN_TEXT;
            }
        }
        
        // 根据内容判断
        if (content != null) {
            content = content.trim();
            
            // 检测JSON格式
            if ((content.startsWith("{") && content.endsWith("}")) ||
                (content.startsWith("[") && content.endsWith("]")) ||
                content.contains("\":\"")) {
                return JsonFileType.INSTANCE;
            }
            
            // 检测断言语法 (如 Entity.property==value)
            if (content.matches(".*[A-Z][a-zA-Z0-9]*\\.[a-zA-Z0-9]+\\s*(==|!=|>|<|>=|<=)\\s*.*")) {
                return ExcelFileType.INSTANCE;
            }

            // 检测Java代码
            if (content.contains("public ") || content.contains("private ") ||
                content.contains("class ") || content.contains("void ") ||
                content.contains("return ")) {
                return FileTypes.PLAIN_TEXT;
            }
        }
        
        // 默认使用纯文本文件类型
        return FileTypes.PLAIN_TEXT;
    }

    private JBTable currentTable;
     
     private void saveCurrentCell() {
        if (currentRow >= 0 && currentColumn >= 0 && editorTextField != null) {
            String newValue = editorTextField.getText();
            // 更新表格数据
            if (currentTable != null) {
                currentTable.setValueAt(newValue, currentRow, currentColumn);
            } else {
                // 如果currentTable为null，尝试从tabbedPane中找到当前活动的表格
                for (Component comp : tabbedPane.getComponents()) {
                    if (comp instanceof JBScrollPane) {
                        JBTable table = (JBTable) ((JBScrollPane) comp).getViewport().getView();
                        table.setValueAt(newValue, currentRow, currentColumn);
                        currentTable = table;
                        break; // 找到表格后退出
                    }
                }
            }
            currentRow = -1;
            currentColumn = -1;
        }
    }
    
    /**
     * 取消编辑，恢复原始值
     */
    private void cancelEditing() {
        if (currentTable != null && currentRow >= 0 && currentColumn >= 0) {
            Object originalValue = currentTable.getValueAt(currentRow, currentColumn);
            editorTextField.setText(originalValue != null ? originalValue.toString() : "");
        }
        currentRow = -1;
        currentColumn = -1;
    }

    @NotNull
    @Override
    public JComponent getComponent() {
        return this.rootPanel;
    }

    @Override
    public @Nullable JComponent getPreferredFocusedComponent() {
        return this.editorTextField;
    }

    @Override
    public @Nls(capitalization = Nls.Capitalization.Title) @NotNull String getName() {
        return "ExcelFileEditor";
    }

    @Override
    public void dispose() {
        // 释放编辑器资源
        if (editorTextField != null && editorTextField.getEditor() != null) {
            EditorFactory.getInstance().releaseEditor(editorTextField.getEditor());
        }
        // 释放其他资源
        project = null;
        currentTable = null;
        editorTextField = null;
    }

    @NotNull
    @Override
    public FileEditorState getState(@NotNull FileEditorStateLevel level) {
        if (this.state == null) {
            this.state = (fileEditorState, fileEditorStateLevel) -> false;
        }
        return state;
    }

    @Override
    public void setState(@NotNull FileEditorState state) {
        this.state = state;
    }

    @Override
    public FileEditorLocation getCurrentLocation() {
        return null;
    }

    @Override
    public VirtualFile getFile() {
        return this.file;
    }

    @Override
    public boolean isModified() {
        return false;
    }

    @Override
    public boolean isValid() {
        return true;
    }

    @Override
    public void selectNotify() {
    }

    @Override
    public void deselectNotify() {
    }

    @Override
    public void addPropertyChangeListener(@NotNull PropertyChangeListener propertyChangeListener) {

    }

    @Override
    public void removePropertyChangeListener(@NotNull PropertyChangeListener propertyChangeListener) {

    }

    @Override
    public <T> @Nullable T getUserData(@NotNull Key<T> key) {
        return null;
    }

    @Override
    public <T> void putUserData(@NotNull Key<T> key, @Nullable T t) {

    }
}
